home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK1.toast / Development Kits (Disc 1) / AOCE / Development Tools / Sample Code / Catalog Service Access Module / DTS Sample CSAM / Src / ProcessPDCommands.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-02  |  16.2 KB  |  570 lines  |  [TEXT/KAHL]

  1. /*                                ProcessPDCommands.c                                */
  2. /*
  3.  * ProcessPDCommands.c
  4.  * Copyright © 1992-93 Apple Computer Inc. All Rights Reserved.
  5.  *
  6.  *
  7.  * ProcessPDCommands is the mainline for all complex requests
  8.  * -- these can potentially initiate I/O. If the request completes
  9.  * without causing additional I/O (for example, if a parameter error
  10.  * prevents continuation), it calls DirRequestCompletion to dequeue
  11.  * the next request. Otherwise, the asychronous I/O request calls
  12.  * DirRequestCompletion when it is done.
  13.  *
  14.  * ProcessPDCommands uses a private parameter block for its
  15.  * I/O requests. If the request was synchronous, ProcessPDCommands
  16.  * makes synchronous requests. If the request was asychronous,
  17.  * ProcessPDCommands makes asychronous requests, using a private
  18.  * completion routine.
  19.  *
  20.  * This private completion routine copies the status code to the
  21.  * user's parameter block and  calls the user's completion routine,
  22.  * if any. When the user's completion routine returns, the private
  23.  * completion routine examines the request queue. If it is not empty,
  24.  * it re-calls ProcessPDCommands to handle the next request.
  25.  *
  26.  * The guts of the code are specific to this particular CSAM.
  27.  *
  28.  * Edit History
  29.  * 8-Jul-1993    MM    Errors from GetRefNumFromRLI (shouldn't happen) now call I/O
  30.  *                    I/O Completion. Also, added DirFindValue and DirFindRecord
  31.  *                    skeletons. Moved GetRefNumFromRLI audit inside the call
  32.  */
  33. #include "DTSSampleCSAM.h"
  34.  
  35. void                DirRequestCompletion(
  36.         DirParamBlockPtr        myPB
  37.     );
  38.  
  39.  
  40. static pascal Boolean MyForEachRecord(
  41.         DirParamBlock            *userPB,
  42.         const DirEnumSpec        *enumSpec
  43.     )
  44. {
  45.  
  46.         OSErr                    status;
  47.         Boolean                    stopNow;
  48.         long                    saveA5;
  49.         char                    buffer[kMinPackedRLISize + kDirectoryNameMaxBytes];
  50.         PackedRLIPtr            prli;
  51.     
  52.         prli = (PackedRLIPtr) buffer;
  53.         stopNow = FALSE;
  54.         if (userPB->findRecordParsePB.forEachRecordFunc != NULL) {
  55.             status = OCEPackRLIParts(
  56.                         userPB->findRecordParsePB.directoryName, 
  57.                         &userPB->findRecordParsePB.discriminator,
  58.                         kRootDNodeNumber,
  59.                         NULL,
  60.                         0,
  61.                         prli,
  62.                         kMinPackedRLISize
  63.                             + kDirectoryNameMaxBytes
  64.                             - sizeof(ProtoPackedRLI)
  65.                     );
  66.             saveA5 = SetA5(userPB->header.saveA5);
  67.             stopNow = userPB->findRecordParsePB.forEachRecordFunc(
  68.                         userPB->header.clientData,
  69.                         enumSpec,
  70.                         prli
  71.                     );
  72.             SetA5(saveA5);
  73.         }
  74.         return (stopNow);
  75. }
  76.  
  77. void
  78. ProcessPDCommands(
  79.         register DTSSampleCSAMInfoPtr    infoPtr,
  80.         register DirParamBlockPtr        pb,
  81.         Boolean                            async
  82.     )
  83. {
  84.         register OSErr            status;
  85.         char                    buffer[kMinPackedRLISize + kDirectoryNameMaxBytes];
  86.         PackedRLIPtr            prli;
  87. #define MYPB        (INFO.dirParamBlock)
  88. #define MYENUMSPEC    (INFO.enumSpec)
  89.  
  90.         prli = (PackedRLIPtr) buffer;
  91.         /*
  92.          * Note: we have to be careful not to touch STATUS (pb->header.ioResult)
  93.          * until the request completes as the user may be bit-spinning on
  94.          * STATUS == ioBusy).
  95.          *
  96.          * Copy the user parameter block into our private parameter block -- so we
  97.          * can use our private ioCompletion and enumeration routines.
  98.          */
  99.         BlockMove(&PARAM, &MYPB, sizeof PARAM);
  100.         status = MemError();
  101.         if (status != noErr)                /* This can't happen    */
  102.             goto exit;
  103.         MYPB.header.ioCompletion =
  104.             (async) ? (ProcPtr) DirRequestCompletion : NULL;
  105.         MYPB.header.clientData = (long) pb;
  106.         MYPB.header.dsRefNum = 0;
  107.         MYPB.header.ioResult = ioBusy;
  108.         switch (MYPB.header.reqCode) {
  109.         case kDirEnumerateParse:
  110.             LogText('PCmd', "\pkDirEnumerateParse");
  111.             status = GetRefNumFromRLI(
  112.                     infoPtr,
  113.                     MYPB.enumerateParsePB.aRLI,
  114.                     &MYPB.header.dsRefNum
  115.                 );
  116.             LogStatus('PCmd', status, "\pGetRefNumFromRLI");
  117.             if (status != noErr)
  118.                 goto fail;
  119.             else {
  120.                 MYPB.enumerateParsePB.eachEnumSpec = MyForEachEnumSpec;
  121.                 status = DirEnumerateParse(&MYPB, async);
  122.                 LogStatus('PCmd', status, "\pDirEnumerateParse");
  123.             }
  124.             break;
  125.         case kDirFindRecordParse:
  126.             LogText('PCmd', "\pkDirFindRecordParse");
  127.             OCEPackRLIParts(
  128.                 pb->findRecordParsePB.directoryName, 
  129.                 &pb->findRecordParsePB.discriminator,
  130.                 kRootDNodeNumber,
  131.                 NULL,
  132.                 0,
  133.                 prli,
  134.                 kMinPackedRLISize + kDirectoryNameMaxBytes - sizeof(ProtoPackedRLI)
  135.             );
  136.             status = GetRefNumFromRLI(
  137.                         infoPtr,
  138.                         prli,
  139.                         &MYPB.header.dsRefNum
  140.                     );
  141.             LogStatus('PCmd', status, "\pGetRefNumFromRLI");
  142.             if (status != noErr)
  143.                 goto fail;
  144.             else {
  145.                 MYPB.enumerateParsePB.eachEnumSpec =
  146.                     (ForEachDirEnumSpec) MyForEachRecord;
  147.                 MYPB.enumerateParsePB.getBuffer = pb->findRecordParsePB.getBuffer;
  148.                 MYPB.enumerateParsePB.getBufferSize = pb->findRecordParsePB.getBufferSize;
  149.                 status = DirEnumerateParse(&MYPB, async);
  150.                 LogStatus('PCmd', status, "\pDirEnumerateParse");
  151.             }
  152.             break;
  153.         case kDirLookupParse:
  154.             LogText('PCmd', "\pkDirLookupParse");
  155.             status = GetRefNumFromRLI(
  156.                         infoPtr,
  157.                         (*MYPB.lookupParsePB.aRecordList)->rli,
  158.                         &MYPB.header.dsRefNum
  159.                     );
  160.             if (status != noErr)
  161.                 goto fail;
  162.             else {
  163.                 MYPB.lookupParsePB.eachRecordID    = MyForEachLookupRecordID;
  164.                 MYPB.lookupParsePB.eachAttrType    = MyForEachAttrTypeLookup;
  165.                 MYPB.lookupParsePB.eachAttrValue    = MyForEachAttrValue;
  166.                 status = DirLookupParse(&MYPB, async);
  167.                 LogStatus('PCmd', status, "\pDirLookupParse");
  168.             }
  169.             break;
  170.         case kDirEnumerateAttributeTypesParse:
  171.             LogText('PCmd',"\pkDirEnumerateAttributeTypesParse");
  172.             status = GetRefNumFromRLI(
  173.                         infoPtr,
  174.                         MYPB.enumerateAttributeTypesParsePB.aRecord->rli,
  175.                         &MYPB.header.dsRefNum
  176.                     );
  177.             if (status != noErr)
  178.                 goto fail;
  179.             else {
  180.                 MYPB.enumerateAttributeTypesParsePB.eachAttrType =
  181.                     MyForEachAttrType;
  182.                 status = DirEnumerateAttributeTypesParse(&MYPB, async);
  183.                 LogStatus('PCmd', status, "\pDirEnumerateAttributeTypesParse");
  184.             }
  185.             break;
  186.         case kDirEnumeratePseudonymParse:
  187.             LogText('PCmd', "\pkDirEnumeratePseudonumParse");
  188.             status = GetRefNumFromRLI(
  189.                         infoPtr,
  190.                         MYPB.enumeratePseudonymParsePB.aRecord->rli,
  191.                         &MYPB.header.dsRefNum
  192.                     );
  193.             if (status != noErr)
  194.                 goto fail;
  195.             else {
  196.                 MYPB.lookupParsePB.eachRecordID = MyForEachRecordID;
  197.                 status = DirEnumeratePseudonymParse(&MYPB, async);
  198.                 LogStatus('PCmd', status, "\pDirEnumeratePseudonymParse");
  199.             }
  200.             break;
  201.         case kDirAddRecord:
  202.             LogText('PCmd', "\pkDirAddRecord");
  203.             status = GetRefNumFromRLI(
  204.                         infoPtr,
  205.                         MYPB.addRecordPB.aRecord->rli,
  206.                         &MYPB.header.dsRefNum
  207.                     );
  208.             if (status != noErr)
  209.                 goto fail;
  210.             else {
  211.                 status = DirAddRecord(&MYPB, async);
  212.                 LogStatus('PCmd', status, "\pDirAddRecord");
  213.             }
  214.             break;
  215.         case kDirDeleteRecord:
  216.             LogText('PCmd', "\pkDirDeleteRecord");
  217.             status = GetRefNumFromRLI(
  218.                         infoPtr,
  219.                         MYPB.deleteRecordPB.aRecord->rli,
  220.                         &MYPB.header.dsRefNum
  221.                     );
  222.             if (status != noErr)
  223.                 goto fail;
  224.             else {
  225.                 status = DirDeleteRecord(&MYPB, async);
  226.                 LogStatus('PCmd', status, "\pDirDeleteRecord");
  227.             }
  228.             break;
  229.         case kDirAddAttributeValue:
  230.             LogText('PCmd', "\pkDirAddAttributeValue");
  231.             status = GetRefNumFromRLI(
  232.                         infoPtr,
  233.                         MYPB.addAttributeValuePB.aRecord->rli,
  234.                         &MYPB.header.dsRefNum
  235.                     );
  236.             if (status != noErr)
  237.                 goto fail;
  238.             else {
  239.                 status = DirAddAttributeValue(&MYPB, async);
  240.                 LogStatus('PCmd', status, "\pDirAddAttributeValue");
  241.             }
  242.             break;
  243.         case kDirDeleteAttributeValue:
  244.             LogText('PCmd', "\pkDirDeleteAttributeValue");
  245.             status = GetRefNumFromRLI(
  246.                         infoPtr,
  247.                         MYPB.deleteAttributeValuePB.aRecord->rli,
  248.                         &MYPB.header.dsRefNum
  249.                     );
  250.             if (status != noErr)
  251.                 goto fail;
  252.             else {
  253.                 status = DirDeleteAttributeValue(&MYPB, async);
  254.                 LogStatus('PCmd', status, "\pDirDeleteAttributeValue");
  255.             }
  256.             break;
  257.         case kDirChangeAttributeValue:
  258.             LogText('PCmd', "\pkDirChangeAttributeValue");
  259.             status = GetRefNumFromRLI(
  260.                         infoPtr,
  261.                         MYPB.changeAttributeValuePB.aRecord->rli,
  262.                         &MYPB.header.dsRefNum
  263.                     );
  264.             if (status != noErr)
  265.                 goto fail;
  266.             else {
  267.                 status = DirChangeAttributeValue(&MYPB, async);
  268.                 LogStatus('PCmd', status, "\pDirChangeAttributeValue");
  269.             }
  270.             break;
  271.         case kDirVerifyAttributeValue:
  272.             LogText('PCmd', "\pkDirVerifyAttributeValue");
  273.             status = GetRefNumFromRLI(
  274.                         infoPtr,
  275.                         MYPB.verifyAttributeValuePB.aRecord->rli,
  276.                         &MYPB.header.dsRefNum
  277.                     );
  278.             if (status != noErr)
  279.                 goto fail;
  280.             else {
  281.                 status = DirVerifyAttributeValue(&MYPB, async);
  282.                 LogStatus('PCmd', status, "\pDirVerifyAttributeValue");
  283.             }
  284.             break;
  285.         case kDirAddPseudonym:
  286.             LogText('PCmd', "\pkDirAddPseudonym");
  287.             status = GetRefNumFromRLI(
  288.                         infoPtr,
  289.                         MYPB.addPseudonymPB.aRecord->rli,
  290.                         &MYPB.header.dsRefNum
  291.                     );
  292.             if (status != noErr)
  293.                 goto fail;
  294.             else {
  295.                 status = DirAddPseudonym(&MYPB, async);
  296.                 LogStatus('PCmd', status, "\pDirAddPseudonym");
  297.             }
  298.             break;
  299.         case kDirDeletePseudonym:
  300.             LogText('PCmd', "\pkDirDeletePseudonym");
  301.             status = GetRefNumFromRLI(
  302.                         infoPtr,
  303.                         MYPB.deletePseudonymPB.aRecord->rli,
  304.                         &MYPB.header.dsRefNum
  305.                     );
  306.             if (status != noErr)
  307.                 goto fail;
  308.             else {
  309.                 DirDeletePseudonym(&MYPB, async);
  310.                 LogStatus('PCmd', status, "\pDirDeletePseudonym");
  311.             }
  312.             break;
  313.         case kDirEnumerateGet:
  314.             LogText('PCmd', "\pkDirEnumerateGet");
  315.             status = GetRefNumFromRLI(
  316.                         infoPtr,
  317.                         MYPB.enumerateGetPB.aRLI,
  318.                         &MYPB.header.dsRefNum);
  319.             if (status != noErr)
  320.                 goto fail;
  321.             else {
  322.                 status = DirEnumerateGet(&MYPB, async);
  323.                 LogStatus('PCmd', status, "\pDirEnumerateGet");
  324.             }
  325.             break;
  326.         case kDirFindRecordGet:
  327.             LogText('PCmd', "\pkDirFindRecordGet");
  328.             OCEPackRLIParts(
  329.                 pb->findRecordParsePB.directoryName, 
  330.                 &pb->findRecordParsePB.discriminator,
  331.                 kRootDNodeNumber,
  332.                 NULL,
  333.                 0,
  334.                 prli,
  335.                 kMinPackedRLISize + kDirectoryNameMaxBytes - sizeof(ProtoPackedRLI)
  336.             );
  337.             status = GetRefNumFromRLI(
  338.                         infoPtr,
  339.                         prli,
  340.                         &MYPB.header.dsRefNum
  341.                     );
  342.             if (status != noErr)
  343.                 goto fail;
  344.             else {
  345.                 if (pb->findRecordGetPB.startingPoint == NULL)
  346.                     MYPB.enumerateGetPB.startingPoint = NULL;
  347.                 else {
  348.                     MYENUMSPEC.enumFlag = kEnumDistinguishedNameMask;
  349.                     MYENUMSPEC.indexRatio = 0;
  350.                     BlockMove(
  351.                         &pb->findRecordGetPB.startingPoint->local,
  352.                         &MYENUMSPEC.u.recordIdentifier,
  353.                         sizeof(LocalRecordID)
  354.                     );
  355.                     MYPB.enumerateGetPB.startingPoint = &MYENUMSPEC;
  356.                 }
  357.                 MYPB.enumerateGetPB.aRLI = NULL;
  358.                 MYPB.enumerateGetPB.sortBy = kSortByName;
  359.                 MYPB.enumerateGetPB.sortDirection = kSortForwards;
  360.                 MYPB.enumerateGetPB.nameMatchString = pb->findRecordGetPB.nameMatchString;
  361.                 MYPB.enumerateGetPB.typesList = pb->findRecordGetPB.typesList;
  362.                 MYPB.enumerateGetPB.typeCount = pb->findRecordGetPB.typeCount;
  363.                 MYPB.enumerateGetPB.enumFlags = kEnumDistinguishedNameMask + kEnumAliasMask + kEnumPseudonymMask;
  364.                 MYPB.enumerateGetPB.includeStartingPoint = false;
  365.                 MYPB.enumerateGetPB.matchNameHow = pb->findRecordGetPB.matchNameHow;
  366.                 MYPB.enumerateGetPB.matchTypeHow = pb->findRecordGetPB.matchTypeHow;
  367.                 MYPB.enumerateGetPB.getBuffer = pb->findRecordGetPB.getBuffer;
  368.                 MYPB.enumerateGetPB.getBufferSize = pb->findRecordGetPB.getBufferSize;
  369.                 status = DirEnumerateGet(&MYPB, async);
  370.                 LogStatus('PCmd', status, "\pDirEnumerateGet");
  371.             }
  372.             break;
  373.         case kDirEnumerateAttributeTypesGet:
  374.             LogText('PCmd', "\pkDirEnumerateAttributeTypesGet");
  375.             status = GetRefNumFromRLI(
  376.                         infoPtr,
  377.                         MYPB.enumerateAttributeTypesGetPB.aRecord->rli,
  378.                         &MYPB.header.dsRefNum
  379.                     );
  380.             if (status != noErr)
  381.                 goto fail;
  382.             else {
  383.                 status = DirEnumerateAttributeTypesGet(&MYPB, async);
  384.                 LogStatus('PCmd', status, "\pDirEnumerateAttributeTypesGet");
  385.             }
  386.             break;
  387.         case kDirEnumeratePseudonymGet:
  388.             LogText('PCmd', "\pkDirEnumeratePseudonymGet");
  389.             status = GetRefNumFromRLI(
  390.                         infoPtr,
  391.                         MYPB.enumeratePseudonymGetPB.aRecord->rli,
  392.                         &MYPB.header.dsRefNum
  393.                     );
  394.             if (status != noErr)
  395.                 goto fail;
  396.             else {
  397.                 status = DirEnumeratePseudonymGet(&MYPB, async);
  398.                 LogStatus('PCmd', status, "\pDirEnumeratePseudonymGet");
  399.             }
  400.             break;
  401.         case kDirGetNameAndType:
  402.             LogText('PCmd', "\pkDirGetNameAndType");
  403.             status = GetRefNumFromRLI(
  404.                         infoPtr,
  405.                         MYPB.getNameAndTypePB.aRecord->rli,
  406.                         &MYPB.header.dsRefNum
  407.                     );
  408.             if (status != noErr)
  409.                 goto fail;
  410.             else {
  411.                 status = DirGetNameAndType(&MYPB, async);
  412.                 LogStatus('PCmd', status, "\pDirGetNameAndType");
  413.             }
  414.             break;
  415.         case kDirSetNameAndType:
  416.             LogText('PCmd', "\pkDirSetNameAndType");
  417.             status = GetRefNumFromRLI(
  418.                         infoPtr,
  419.                         MYPB.setNameAndTypePB.aRecord->rli,
  420.                         &MYPB.header.dsRefNum
  421.                     );
  422.             if (status != noErr)
  423.                 goto fail;
  424.             else {
  425.                 status = DirSetNameAndType(&MYPB, async);
  426.                 LogStatus('PCmd', status, "\pDirSetNameAndType");
  427.             }
  428.             break;
  429.         case kDirGetRecordMetaInfo:
  430.             LogText('PCmd', "\pkGetRecordMetaInfo");
  431.             status = GetRefNumFromRLI(
  432.                         infoPtr,
  433.                         MYPB.getRecordMetaInfoPB.aRecord->rli,
  434.                         &MYPB.header.dsRefNum
  435.                     );
  436.             if (status != noErr)
  437.                 goto fail;
  438.             else {
  439.                 status = DirGetRecordMetaInfo(&MYPB, async);
  440.                 LogStatus('PCmd', status, "\pDirGetRecordMetaInfo");
  441.             }
  442.             break;
  443.         case kDirLookupGet:
  444.             LogText('PCmd', "\pkDirLookupGet");
  445.             status = GetRefNumFromRLI(
  446.                         infoPtr,
  447.                         (*MYPB.lookupGetPB.aRecordList)->rli,
  448.                         &MYPB.header.dsRefNum
  449.                     );
  450.             if (status != noErr)
  451.                 goto fail;
  452.             else {
  453.                 status = DirLookupGet(&MYPB, async);
  454.                 LogStatus('PCmd', status, "\pDirLookupGet");
  455.             }
  456.             break;
  457.         case kDirGetDNodeMetaInfo:
  458.             LogText('PCmd', "\pkDirGetDNodeMetaInfo");
  459.             status = GetRefNumFromRLI(
  460.                         infoPtr,
  461.                         MYPB.getDNodeMetaInfoPB.pRLI,
  462.                         &MYPB.header.dsRefNum
  463.                     );
  464.             if (status != noErr)
  465.                 goto fail;
  466.             else {
  467.                 status = DirGetDNodeMetaInfo(&MYPB, async);
  468.                 LogStatus('PCmd', status, "\pDirGetDNodeMetaInfo");
  469.             }
  470.             break;
  471.         case kDirAddAlias:
  472.             LogText('PCmd', "\pkDirGetRefNumFromRLI");
  473.             status = GetRefNumFromRLI(
  474.                         infoPtr,
  475.                         MYPB.addAliasPB.aRecord->rli,
  476.                         &MYPB.header.dsRefNum
  477.                     );
  478.             if (status != noErr)
  479.                 goto fail;
  480.             else {
  481.                 status = DirAddAlias(&MYPB, async);
  482.                 LogStatus('PCmd', status, "\pDirAddAlias");
  483.             }
  484.             break;
  485.         case kDirDeleteAttributeType:
  486.             LogText('PCmd', "\pkDirDeleteAttributeType");
  487.             status = GetRefNumFromRLI(
  488.                         infoPtr,
  489.                         MYPB.deleteAttributeTypePB.aRecord->rli,
  490.                         &MYPB.header.dsRefNum
  491.                     );
  492.             if (status != noErr)
  493.                 goto fail;
  494.             else {
  495.                 status = DirDeleteAttributeType(&MYPB, async);
  496.                 LogStatus('PCmd', status, "\pDirDeleteAttributeType");
  497.             }
  498.             break;
  499.         case kDirFindValue:
  500.             LogText('PCmd', "\pkDirFindValue");
  501.             {
  502.                 status = controlErr;        //** TBS: Code not written yet
  503.                 goto fail;
  504.             }
  505.             break;
  506.         default:
  507.             /*
  508.              * Error: incorrect request code.
  509.              */
  510. #if DEBUG_LOG
  511.             AuditStatusLocation(INFO.auditPtr, 'Cmd?', MYPB.header.reqCode);
  512. #endif
  513.             status = controlErr;
  514.             /*
  515.              * goto fail with errors.
  516.              */
  517. fail:        MYPB.header.ioResult = status;
  518.             if (async)
  519.                    DirRequestCompletion(&MYPB);
  520.             break;
  521.         }
  522. exit:    STATUS = status;
  523.         LogStatus('PSts', STATUS, "\pProcessPDCommands exit");
  524. #undef MYPB
  525. }
  526.  
  527. /*
  528.  * This is the completion routine called by the Dir... routines when
  529.  * one of the above requests complete. It does the following:
  530.  *
  531.  * 1. remove the user parameter block from the request queue.
  532.  * 2. call the user completion routine, if any.
  533.  * 3. if there is still something in the request queue, call
  534.  *    ProcessPDCommands to start working on it. Note that
  535.  *      this call "must" be asychronous. The only way to have
  536.  *    several things in the request queue is for all of them
  537.  *    (except, possibly, the first) to be asychronous.
  538.  */
  539. void
  540. DirRequestCompletion(
  541.         DirParamBlockPtr        myPB
  542.     )
  543. {
  544.         DirParamBlockPtr        userPB;
  545.         DirParamBlockPtr        nextPB;
  546. #define infoPtr        ((DTSSampleCSAMInfoPtr) myPB)
  547.  
  548. #if DEBUG_LOG
  549.         if (myPB->header.ioResult != noErr)
  550.             AuditStatusLocation(INFO.auditPtr, 'DiRC', myPB->header.ioResult);
  551. #endif
  552.         userPB = (DirParamBlockPtr) myPB->header.clientData;
  553.         if (myPB->header.ioResult == ioBusy || userPB == NULL)
  554.             AuditStatusLocation(INFO.auditPtr, 'DiRC', myPB->header.ioResult);
  555.         else {
  556.             /*
  557.              * Copy completion code to user function and call the user's completion
  558.              * routine (if any). The queue management duplicates DequeueFirst() logic.
  559.              */
  560.             userPB->header.ioResult = myPB->header.ioResult;
  561.             CallCompletion((ParmBlkPtr) userPB);
  562.             nextPB = (DirParamBlockPtr) INFO.requestQueueHdr.qHead;
  563.             if (nextPB != NULL) {
  564.                 if (Dequeue((QElemPtr) nextPB, &INFO.requestQueueHdr) == noErr) {
  565.                     ProcessPDCommands(infoPtr, nextPB, TRUE);
  566.                 }
  567.             }
  568.         }
  569. }
  570.